package jxta.chat.util;

import java.io.IOException;

import jxta.chat.PipeHolder;
import jxta.test.JxtaManager;
import net.jxta.endpoint.Message;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.pipe.PipeMsgListener;
import net.jxta.util.JxtaBiDiPipe;

/**
 * Sends a message to a remote peer
 */
public class RemoteMessageSender {

	public final int INETRVAL = 250;
	
	private	PipeMsgListener listener;
	private boolean gotResponse;
	
	public void setListener(PipeMsgListener listener){
		this.listener = listener;
	}
	
	/**
	 * Sends a message with out a response 
	 * @param chatMAnager TODO
	 * @param message the message we want to send
	 * @param peerName the peerName that we want to send a message to
	 */
	public void sendMessage(JxtaManager chatMAnager, Message message, String peerName){
		sendRemoteMessage(null, message, false, null, peerName);
	}
	
	/**
	 * Sends a message with a response 
	 * @param chatManager TODO
	 * @param message the message we want to send
	 * @param responseTimeOut timeout value that we'll wait for a response
	 * @param peerName the peerName that we want to send a message to
	 */
	public void sendMessage(JxtaManager chatManager, Message message, long responseTimeOut, String peerName){
		sendRemoteMessage(null, message, true, responseTimeOut, peerName);
	}
	
	/**
	 * Sends a message to a remote peer
	 * @param chatManager TODO
	 * @param msg the message we want to send
	 * @param needResponse mark if we want to wait for a response
	 * @param responseTimeOut a timeout that we'll wait for a response. in case we don't want to wait
	 * the value will be null
	 * @param peerName the name of the peer that we want to send a message to
	 */
	private void sendRemoteMessage(JxtaManager chatManager, Message msg, boolean needResponse, 
								   Long responseTimeOut, String peerName){
		
		JxtaBiDiPipe pipe = PipeHolder.getInstance().getPipe(peerName);
		gotResponse = false;
		
		PipeMsgListener oldListener = null;
		
		if (needResponse){
			oldListener = pipe.getMessageListener();
			
			// Switch the old listener with a new one only for the request
			pipe.setMessageListener(new PipeMsgListener(){
				public void pipeMsgEvent(PipeMsgEvent arg0) {
					gotResponse = true;
					listener.pipeMsgEvent(arg0);
				}
			});
		}
		
		// Send a message on the pipe
		try {
			pipe.sendMessage(msg);
		} catch (IOException e) {
			System.out.println("Error sending a message to peer " + peerName + ". error: " + e.getMessage());
		}

		// Wait until we'll get a response
		if (needResponse && responseTimeOut != null){
			
			long m = System.currentTimeMillis() + responseTimeOut;
			
            while (!gotResponse && m > System.currentTimeMillis()) {
                try {
                    Thread.sleep(INETRVAL);
                } catch (InterruptedException ie) {
                    m = 0;
                }
            }
            
            pipe.setMessageListener(oldListener);
		}
	}	
}
